package com.koc.robot.util;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import java.util.ArrayList;

public class BufferUtils 
{
	static ArrayList<ByteBuffer> unsafeBuffers = new ArrayList<ByteBuffer>();
	static int allocatedUnsafe = 0;
	
	public static void disposeUnsafeByteBuffer(ByteBuffer buffer)
	{
		int size = buffer.capacity();
		synchronized(unsafeBuffers)
		{
			if (!unsafeBuffers.remove(buffer))
			{
				throw new IllegalArgumentException("buffer not allocated with newUnsafeByteBuffer or already disposed");
			}
		}
		allocatedUnsafe -= size;
		freeMemory(buffer);
	}
	
	public static ByteBuffer newUnsafeByteBuffer(int numBytes)
	{
		ByteBuffer buffer = newDisposableByteBuffer(numBytes);
		buffer.order(ByteOrder.nativeOrder());
		allocatedUnsafe += numBytes;
		synchronized(unsafeBuffers)
		{
			unsafeBuffers.add(buffer);
		}
		
		return buffer;
	}
	
	public static void copy(byte[] src, int srcOffset, Buffer dst, int numElements)
	{
		copyJni(src, srcOffset, dst, positionInBytes(dst), numElements);
		dst.limit(dst.position() + bytesToElements(dst, numElements));
	}
	
	private static int positionInBytes(Buffer dst)
	{
		if (dst instanceof ByteBuffer)
			return dst.position();
		else
			throw new RuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
	}
	
	private static int bytesToElements(Buffer dst, int bytes)
	{
		if (dst instanceof ByteBuffer)
			return bytes;
		else
			throw new RuntimeException("Can't copy to a " + dst.getClass().getName() + " instance");
	}
	
	private static native void freeMemory(ByteBuffer buffer);
	
	private static native ByteBuffer newDisposableByteBuffer(int numBytes);
	
	private native static void copyJni(byte[] src, int srcOffset, Buffer dst, int dstOffset, int numBytes);
}
